A Brief Discussion on Environment Name Configuration and Application in ASP.NET Core
The motivation for this article stems from a colleague's unfamiliarity with ASP.NET Core deployment, combined with some details I had previously misunderstood, prompting me to compile this information.
Configuration Settings
In the legacy .NET Framework, configuration settings were primarily used to switch between different configuration files. For detailed information, please refer to "Regarding the Application of Web.config (App.config) in .NET Framework". Using Web.config as the primary file, the content of Web.config is overridden via Web.{Configuration}.config. Within each configuration, corresponding constants can be defined and switched using conditional compilation.
Environment Names
In .NET Core and .NET 5 and later versions, in addition to configuration settings, the environment variable EnvironmentName has been added to distinguish between different environments. EnvironmentName can be any value, but ASP.NET Core provides the following default values:
- Development: Used for local development.
- Staging: Used for pre-release versions.
- Production: The default value if
DOTNET_ENVIRONMENTandASPNETCORE_ENVIRONMENTare not set; generally used for the production environment.
These three environment names can correspond to the master, pre-production, and production branches of GitLab Flow. If GitLab Flow defines other environment branches, corresponding environment names can also be set.
In ASP.NET Core, appsettings.json is primarily used as the configuration file, and appsettings.{Environment}.json is used to override the content of the primary configuration file. The difference from the legacy Web.config is that Web.config uses the Web.{Configuration}.config Transform mechanism to generate a new Web.config after build; whereas appsettings.json follows a loading order where later loaded settings override previous ones.
When ASP.NET Core executes WebApplication.CreateBuilder(args), it internally calls the extension method HostingHostBuilderExtensions.ConfigureDefaults(), which loads appsettings.json and appsettings.{Environment}.json. Below is an excerpt of the code:
builder.ConfigureAppConfiguration((hostingContext, config) => {
IHostEnvironment env = hostingContext.HostingEnvironment;
bool reloadOnChange = GetReloadConfigOnChangeValue(hostingContext);
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);
if (env.IsDevelopment() && env.ApplicationName is { Length: > 0 }) {
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly is not null) {
config.AddUserSecrets(appAssembly, optional: true, reloadOnChange: reloadOnChange);
}
}
config.AddEnvironmentVariables();
if (args is { Length: > 0 }) {
config.AddCommandLine(args);
}
})WARNING
Since ASP.NET Core internally loads appsettings.json and appsettings.{Environment}.json, manually loading appsettings.json again might override the settings in appsettings.{Environment}.json. I once failed to load appsettings.{Environment}.json for unknown reasons and, misled by the Web.config mindset, added these two lines in Program for testing. I then tried commenting out the reference to appsettings.{Environment}.json and was confused as to why the settings weren't being picked up. It wasn't until I saw a colleague comment out both lines for testing that I realized where the problem was.
Methods for Setting Environment Variables
Local Development
ASP.NET Core allows setting the local development environment in the Properties\launchSettings.json file. The environment value set here will appear in the Visual Studio simulator list and will override global environment settings. The following is a default example; for more specific settings, please refer to the MSDN article "Development and launchSettings.json".
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59481",
"sslPort": 44308
}
},
"profiles": {
"Sample": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7152;http://localhost:5105",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}Using Visual Studio Publish
For the publishing method, please refer to the Web Project Publishing section of my previous article. Although it was written for the ASP.NET version, the operation for ASP.NET Core is the same. The only difference is that you need to add the following content to the XML to set the environment name:
<EnvironmentName>Staging</EnvironmentName>After publishing, the following content will be added to Web.config, and IIS will use this content as the value for the environment variable:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\KunYou.KyFido.Backend.WebApi.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
<!--Extra generated content settings-->
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
</configuration>TIP
In the past, when setting Publish.xml in ASP.NET, you could set <ExcludeFilesFromDeployment> or <ExcludeFoldersFromDeployment> to exclude specific files or folders. However, this setting is ineffective in ASP.NET Core, so you cannot use it to exclude redundant appsettings.{Environment}.json files.
Using Dockerfile Configuration
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
# Add this line to set the environment variable
ENV ASPNETCORE_ENVIRONMENT=StagingOperating Environment Settings
ASP.NET Core uses the IWebHostEnvironment object to define environment-related operations. The IHostEnvironment implemented by this interface defines the EnvironmentName property. Additionally, the extension methods IsDevelopment(), IsStaging(), and IsProduction() are defined in HostEnvironmentEnvExtensions to determine the current environment name at runtime. For custom environment names, you can use IsEnvironment({environmentName}) to determine the environment.
Change Log
- 2024-07-12 Initial version created.